﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Concurrent;
using WebApi.Models;

namespace WebApi.Controllers
{
    /// <summary>
    /// VCardController
    /// </summary>
    [Route("api/[controller]")]
    [ApiController]
    public class VCardController : ControllerBase
    {
        private static readonly ConcurrentDictionary<Guid, Contact> _contacts = new();

        private static void Add(Contact contact)
        {
            contact.Id = Guid.NewGuid();
            _contacts.TryAdd(contact.Id, contact);
        }

        /// <summary>
        /// Test method to throw an exception.
        /// </summary>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        [HttpGet("ThrowError")]
        public IActionResult Throw()    
        {
            throw new Exception("This is a test exception");
        }

        /// <summary>
        /// Get all contacts.
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public ActionResult<IEnumerable<Contact>> Get()
        {
            return Ok(_contacts.Values);
        }

        /// <summary>
        /// Get a contact by id.
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("{id:guid}")]
        public ActionResult<Contact> Get(Guid id)
        {
            if (_contacts.TryGetValue(id, out var contact))
            {
                return Ok(contact);
            }
            return NotFound();
        }

        /// <summary>
        /// Create a new contact.
        /// </summary>
        /// <param name="contact"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult<Contact> Post([FromBody] Contact contact)
        {
            if (contact == null)
            {
                return BadRequest();
            }
            Add(contact);
            return CreatedAtAction(nameof(Get), new { id = contact.Id }, contact);
        }

        /// <summary>
        /// Update an existing contact.
        /// </summary>
        /// <param name="id"></param>
        /// <param name="contact"></param>
        /// <returns></returns>
        [HttpPut("{id:guid}")]
        public ActionResult<Contact> Put(Guid id, [FromBody] Contact contact)
        {
            if (contact == null || id != contact.Id)
            {
                return BadRequest();
            }
            if (_contacts.TryUpdate(id, contact, _contacts[id]))
            {
                return NoContent();
            }
            return NotFound();
        }

        /// <summary>
        /// Delete a contact by id.
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpDelete("{id:guid}")]
        public ActionResult Delete(Guid id)
        {
            if (_contacts.TryRemove(id, out _))
            {
                return NoContent();
            }
            return NotFound();
        }
    }
}
